#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <assert.h>
#include "m.h"
#include "crc32.h"

extern unsigned long long *head,*tail,*total_item_num;
extern void *m;

void *open_db(char *db_name,unsigned int size,int create)
{
	int fd,flag;
	if (create == 3) // use malloc instead of mmap
	{
		m=malloc(size);
		if(!m)
		{
			perror("malloc");
			return NULL;
		}
	}
	else //use mmap
	{
		if (create == 1) 
			flag=O_RDWR|O_CREAT|O_TRUNC;
		if (create == 0)	
			flag=O_RDWR;
		if((fd=open(db_name,flag,S_IRWXU)) < 0)
		{
			perror("open");
			return NULL;
		}
		if(ftruncate(fd,size) != 0)
		{
			perror("ftruncate");
			return NULL;
		}
		if((m=mmap(0,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED)
		{
			perror("mmap");
			return NULL;
		}
	}
	head=(long long *)m;
	tail=((long long *)m)+1;
	total_item_num=((long long *)m)+2;
	if(create !=0)
	{
		*head=3*sizeof(long long);
		*tail=3*sizeof(long long);
		*total_item_num=0;
	}
	return m;
}
int write_cell(void *m,int size,int flag1,int flag2,void *data)
{
	unsigned int cr=generate_crc32c(data,size);
	memcpy(m,&size,sizeof(int));
	m+=sizeof(int);
	//memcpy(m,&flag1,sizeof(int));
	memcpy(m,&cr,sizeof(int));
	m+=sizeof(int);
	memcpy(m,&flag2,sizeof(int));
	m+=sizeof(int);
	memcpy(m,data,size);
	return size+3*sizeof(int);
}
int read_cell(void *m,int *size,int *flag1,int *flag2,void **data)
{
	memcpy(size,m,sizeof(int));
	m+=sizeof(int);
	unsigned int crs,cr;
	memcpy(&crs,m,sizeof(int));
	memcpy(flag1,m,sizeof(int));
	m+=sizeof(int);
	memcpy(flag2,m,sizeof(int));
	m+=sizeof(int);
	cr=generate_crc32c(m,*size);
	assert(cr == crs); 
	*data=m;
	return *size+3*sizeof(int);
}
void close_db(void)
{
	//munmap(m,1024*1024);
}
/*
int main(int argc,char **argv)
{
	char *db = argc == 2 ? argv[1] : "test";
	void *m=open_db(db,1024*1024,0);
	printf("head: %d,tail %d\n",*head,*tail);
	*head+=write_cell(m+(*head),7,1,1,"abcdefghik");
	int size,flag1,flag2;
	void *s;
	*tail+=read_cell(m+(*tail),&size,&flag1,&flag2,&s);
	void *data=calloc(1,size);
	memcpy(data,s,size);
	printf("head: %d,tail %d\n",*head,*tail);
	printf("size,flag1,flag2,data: %d,%d,%d,%s\n",size,flag1,flag2,data);
	free(data);
}
*/
